// Copyright (c) 2021 Presto Labs Pte. Ltd.
// Author: daniel

#pragma once

#include <memory>
#include <string>
#include <string_view>

#include "coin2/base/window/time_window.h"
#include "coin2/exchange/base/order/order.h"
#include "coin2/exchange/order/risk_manager.pb.h"

namespace coin2::exchange::risk {

class RestErrorStats {
 public:
  explicit RestErrorStats(const int64_t window_size)
      : window_size_(window_size), request_window_{window_size} {}
  void HandleRestError(int64_t ts) { request_window_.Push(ts, 1); }

  int64_t num_of_rest_errors() const { return request_window_.sum(); }

  int64_t window_size() const { return window_size_; }

  void UpdateTimestamp(int64_t ts) {
    if (ts >= current_ts_) {
      current_ts_ = ts;
      request_window_.Push(ts, 0);
    }
  }

 private:
  int64_t window_size_{60'000'000'000LL};
  coin2::base::window::TimeMovingWindow request_window_;
  int64_t current_ts_{0};
};

class RiskManager {
 public:
  using RiskManagerConfig = coin2::exchange::order::RiskManagerConfig;
  using OrderUpdate = exchange::base::order::OrderUpdate;

 public:
  explicit RiskManager(const RiskManagerConfig& config);
  void UpdateTimestamp(int64_t ts) {
    if (ts >= current_ts_) {
      current_ts_ = ts;
    }
  }

  int64_t num_of_rest_errors() const {
    rest_error_stats_->UpdateTimestamp(GetCurrentTimestamp());
    return rest_error_stats_->num_of_rest_errors();
  }

  int64_t rest_stat_window_size() const { return rest_error_stats_->window_size(); }

  void HandleOrderUpdate(const OrderUpdate& upd);

 private:
  const RiskManagerConfig config_;
  std::unique_ptr<RestErrorStats> rest_error_stats_;
  int64_t current_ts_{0};
};

}  // namespace coin2::exchange::risk
